package com.gitee.cashzhang27.test.boot.other.entity;


import cn.hutool.json.JSONUtil;
import com.gitee.cashzhang27.test.boot.other.constant.LogConstants;
import com.gitee.cashzhang27.test.boot.other.util.NetUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;

/**
 * @author Cash Zhang
 * @version v1.0
 * @since 2019/06/14 14:54
 */
@Slf4j
public class LogTrace {


  private final static String APPLICATION_JSON = "application/json";

  /**
   * 请求前日志打印
   *
   * @param request request
   */
  private void preLogTrace(HttpServletRequest request) throws IOException {

    Long startTime = System.currentTimeMillis();
    Map<String, Object> json = new HashMap<>(1 << 4);
    // 用户ip
    json.put(LogConstants.IP, NetUtils.getClientIpAddress(request));
    // 请求路径
    json.put(LogConstants.REQ_PATH, request.getRequestURI());
    // 请求参数
    if (APPLICATION_JSON.equals(request.getContentType())) {
      String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
      json.put("body", body);
    } else {
      Map<String, String[]> map = request.getParameterMap();
      map.forEach((key, value) -> json.put(key, request.getParameter(key)));
    }
    // 记录请求开始时间
    request.setAttribute(LogConstants.START_TIME, startTime);

    log.info(LogConstants.REQUEST_DATA + JSONUtil.toJsonStr(json));
  }

  /**
   * 请求后日志打印
   *
   * @param request request
   */
  private void afterLogTrace(HttpServletRequest request) {
    Map<String, Object> json = new HashMap<>(1 << 4);
    Long startTime = (Long) request.getAttribute(LogConstants.START_TIME);
    // 请求耗时
    json.put(LogConstants.CONSUME_TIME, System.currentTimeMillis() - startTime);
    // 响应Data
    json.put(LogConstants.RES_BODY, request.getAttribute(LogConstants.RES_BODY));

    log.info(LogConstants.RESPONSE_DATA + JSONUtil.toJsonStr(json));
  }

  /**
   * 打印请求日志
   *
   * @param servletRequest servletRequest
   */
  @Async
  public void printPreLog(ServletRequest servletRequest) throws IOException {
    if (servletRequest instanceof HttpServletRequest) {
      preLogTrace((HttpServletRequest) servletRequest);
    }
  }

  /**
   * 打印响应日志
   *
   * @param servletRequest servletRequest
   */
  @Async
  public void printAfterLog(ServletRequest servletRequest) {
    if (servletRequest instanceof HttpServletRequest) {
      afterLogTrace((HttpServletRequest) servletRequest);
    }
  }
}
